/**
 * @file   MiraIRobot2D.h
 * @author Josep Sabater (jsabaterm@el.ub.edu)
 * @date   November, 2016
 * @version 1.0.0
 * @ingroup QMira
 * @brief  Interface for a generic Low Level Robot2D
 *
 * Contains the methods each Low Level Robot must implement.
 */
#ifndef MIRA_I_ROBOT_2D_H
#define MIRA_I_ROBOT_2D_H

#include <MiraTypes.h>
#include <MiraPlacement2D.h>

#include "MiraJoint2D.h"
#include "QMiraDefs.h"


namespace QMira{
    /**
     * @class IRobot2D
     * @brief Interface to implement by any Low Level 2D Robot
     */
    class IRobot2D {
    public:
        
        /* Unique id used to identify each robot */
        typedef QMira::Ident_t IRobot2DId_t;
        
        /**
         * @class Status
         * @brief Displays the robot status
         */        
        enum class Status {
            NOT_WORKING = 0, //!<  The robot is kaputt, it cannot be safely used
            AVAILABLE,  //!< the robot is operative and can be safely used.        
        };
        
        /**
         * @brief Enum showing the direction the arm is pointing to.
         */
        enum class Pointing {
            Forward, // !< The robot is pointing forward (tip on the right side)
            Backward // !< The robot is pointing backward (tip on the left side)
        };

        /**
         * @brief Virtual destructor
         */  
        virtual ~IRobot2D() = default;
        
        /**
         * @brief Returns an unique id identifying the robot.
         */          
        virtual IRobot2DId_t id() const = 0;
        
        /**
         * @brief Returns the robot status (getter)
         */          
        virtual Status status() const = 0;
        
        /**
         * @brief Sets the robot status (setter)
         */               
        virtual void status(const Status &st) = 0;
        
        /**
         * @brief Returns (RVO) the qs of the robot according to the World frame.
         */
        virtual MiraUtilUBLib::DoubleCont_t getQs() const = 0;

        /**
         * @brief Returns (RVO) the placement of all joints
         * @param qs a container of state variables (q). Lengths in mm. and
         * angles in degrees.
         * The joint placements is according to the World frame. 
         * Position comes in mm and orientation in degrees.
         * 
         */
        virtual Joint2D::Joint2DCont_t getJoints(const MiraUtilUBLib::DoubleCont_t &qs) const = 0;
        
        
        /**
         * @brief Returns the link lengths.
         */
        virtual const MiraUtilUBLib::DoubleCont_t& getLinksLength() const = 0;        
        
        /**
         * @brief Translate a given point in the robot frame into 
         *a point in the World frame.
         * @param aPoint a 2D point expressed according to robot frame.
         */
        virtual MiraGeometryLib::Vector2D robot2World(const MiraGeometryLib::Vector2D &aPoint) const = 0;

        /**
         * @brief Translate a given point in the World frame into 
         *a point in the robot  frame.
         * @param aPoint a 2D point expressed according to World frame.
         */
        virtual MiraGeometryLib::Vector2D world2Robot(const MiraGeometryLib::Vector2D &wPoint) const = 0;

        /**
         * @brief Build a string with representative information of the arm.
         */
        virtual std::string str() const = 0;
        
        /* Useful typedefs */
        typedef std::unique_ptr <IRobot2D> IRobot2DUniquePtr_t;
        typedef std::vector<IRobot2DUniquePtr_t> IRobot2DUniqueCont_t;        
    };
}

#endif /*QMIRA_I_ROBOT_2D_H*/
